package gorm

import (
	"gitee.com/zacyuan/yuan/pkg/log"
)

type Handler func(*DB)

type Hook func(name string, next Handler) Handler

func LogInterceptor() Hook {
	return func(name string, next Handler) Handler {
		return func(scope *DB) {
			next(scope)
			log.FormContext(scope.Statement.Context).Infof("ExecSQL: %s", scope.Dialector.Explain(scope.Statement.SQL.String(), scope.Statement.Vars...))
			log.FormContext(scope.Statement.Context).Infof("RowsAffected:%d|Error: %v", scope.RowsAffected, scope.Error)
		}
	}
}

type Processor interface {
	Get(name string) func(*DB)
	Replace(name string, handler func(*DB)) error
}

func RegisterHook(db *DB, interceptors ...Hook) error {
	var processors = []struct {
		Name      string
		Processor Processor
	}{
		{"gorm:create", db.Callback().Create()},
		{"gorm:query", db.Callback().Query()},
		{"gorm:delete", db.Callback().Delete()},
		{"gorm:update", db.Callback().Update()},
		{"gorm:row", db.Callback().Row()},
		{"gorm:raw", db.Callback().Raw()},
	}

	for _, interceptor := range interceptors {
		for _, processor := range processors {
			handler := processor.Processor.Get(processor.Name)
			handler = interceptor(processor.Name, handler)
			err := processor.Processor.Replace(processor.Name, handler)
			if err != nil {
				return err
			}
		}
	}

	return nil
}
